package com.lpf.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.lpf.service.HelloService;
import org.apache.skywalking.apm.toolkit.trace.ActiveSpan;
import org.apache.skywalking.apm.toolkit.trace.RunnableWrapper;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@RestController
@RequestMapping("/")
public class HelloWorldController {

    private static final Logger LOGGER = LoggerFactory.getLogger(HelloWorldController.class);

    @Reference
    private HelloService helloService;

    // 启动一个单线程的线程池
    private final ExecutorService executorService = Executors.newSingleThreadScheduledExecutor();

    /**
     * 通过 Dubbo 远程调用 demo-provider 暴露的接口
     */
    @GetMapping("/hello/{words}")
    public String hello(@PathVariable("words") String words) throws Exception {
        Thread.sleep(1000);

        // TraceContext 工具类定义在 apm-toolkit-trace 依赖包中
        LOGGER.info("traceId:{}", TraceContext.traceId());

        ActiveSpan.tag("hello-trace", words);
        String say = helloService.say(words);
        Thread.sleep(1000);

        // helloService.traceMethod();

        // 通过 RunnableWrapper 包装 Runnable 实现 Trace 的跨线程传播
        // 通过 CallableWrapper 包装 Callable 实现 Trace 的跨线程传播
        // 《Trace信息跨线程传播的核心原理.png》
        executorService.submit(
                // 使用 RunnableWrapper 对 Runnable 进行包装，实现 Trace 跨线程传播
                RunnableWrapper.of(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            helloService.traceMethod();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                })
        );

        return say;
    }

    /**
     * 直接抛出 RuntimeException 异常
     */
    @GetMapping("/err")
    public String err() {
        String traceId = TraceContext.traceId();
        LOGGER.info("traceId:{}", traceId);
        ActiveSpan.tag("error-trace activation", "error");
        throw new RuntimeException("err");
    }
}